package com.jdh.controller;

import com.jdh.common.Constant;
import com.jdh.model.ChatMessage;
import com.jdh.model.User;
import com.jdh.util.Result;
import com.jdh.vo.UserRoomDataVo;
import com.jdh.vo.UserRoomVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.web.bind.annotation.*;

import java.security.Principal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName: ChatController
 * @Author: jdh
 * @CreateTime: 2022-11-17
 * @Description: 一些常规的http请求类
 */
@RestController
@RequestMapping("/chatRoom")
public class ChatRoomController {

    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    /**
     * 本demo的精髓所在，所有的聊天或者群聊都是这个接口中实现的，好友一对一聊天也是通过订阅地址的不同来完成的
     * 其实可用用sendToUser来完成，但是为了方便就没有写，ChatRoomController中预留了一个@sendToUser或者convertAndSendToUser的测试接口
     * @param chatMessage
     * @param user
     * @param headerAccessor
     * @return
     */
    @MessageMapping("/user.sendMessage") // 定义消息发送的请求地址
    public String userSendMessage(@Payload ChatMessage chatMessage, User user, SimpMessageHeaderAccessor headerAccessor) {
        String subUrl = "";
        if ("1".equals(chatMessage.getMsgType())) {
            String onlyTag = Constant.getOnlyTag(chatMessage.getSenderUuid(), chatMessage.getReceiverUuid());
            //如果是单发，就记录发送者的消息,key采用发送者uuid+接收者uuid
            List<ChatMessage> messageList = Constant.ownChatMsgList.get(onlyTag);
            if (messageList == null) {
                messageList = new ArrayList<>();
            }
            messageList.add(chatMessage);
            Constant.ownChatMsgList.put(onlyTag, messageList);
            //需要转发的地址，此处是转发给指定好友订阅的路径
            subUrl = "/own/" + chatMessage.getReceiverUuid() + "/" + chatMessage.getSenderUuid() + "/messages";
        } else {
            //如果是群发，就记录为该群对应的消息
            List<ChatMessage> messageList = Constant.ownChatMsgList.get(chatMessage.getReceiverUuid());
            if (messageList == null) {
                messageList = new ArrayList<>();
            }
            messageList.add(chatMessage);
            Constant.ownChatMsgList.put(chatMessage.getReceiverUuid(), messageList);
            //需要转发的地址，此处是转发给指定群消息订阅路径
            subUrl = "/topic/" + chatMessage.getReceiverUuid() + "/queue/messages";
        }
        String info = chatMessage.getSenderUuid() + " 发送消息 '" + chatMessage.getSendContent() + "' 给 " + chatMessage.getReceiverUuid();
        System.out.println(info + "; 转发路径:" + subUrl);
        //因为转发的路径是不同的，所以就没有使用@sendTo或者@sendToUser注解来实现消息转发
        simpMessagingTemplate.convertAndSend(subUrl, chatMessage);

        return "消息推送成功！";
    }

    /**
     * 获取当前未被登录的用户信息
     * @return
     */
    @PostMapping("/getAllUserList")
    public Result<List<User>> getAllUserList() {
        HashMap<String, User> allUserData = Constant.allUserDataList;
        List<String> onlineUserList = Constant.onlineUserList;
        //查询出当前可用的用户集合，即未登录的账户
        List<User> newUserList = allUserData.entrySet().stream()
                .filter(entry -> (!onlineUserList.contains(entry.getKey()) && Constant.allUserList.contains(entry.getKey())))
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

        return Result.success(newUserList);
    }

    /**
     * 获取当前登录的用户信息，包括好友列表
     * @param user
     * @return
     */
    @PostMapping("/getUserData")
    public Result<UserRoomDataVo> getUserData(@RequestBody User user) {
        if (Constant.onlineUserList.contains(user.getUuid())) {
            return Result.error("当前账户已在别处登录;请重新获取再选择账户！");
        }

        User ownUser = Constant.allUserDataList.get(user.getUuid());
        List<String> list = Constant.ownFriendList.get(user.getUuid());

        //查询出当前用户对应的好友列表
        List<User> friendList = Constant.allUserDataList.entrySet().stream()
                .filter(entry -> (list.contains(entry.getKey())))
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

        UserRoomDataVo userRoomDataVo = new UserRoomDataVo();
        userRoomDataVo.setUser(ownUser);
        userRoomDataVo.setFriendList(friendList);

        //当前用户设置为已上线的账户
        Constant.onlineUserList.add(user.getUuid());

        return Result.success(userRoomDataVo);
    }

    /**
     * 用户点击下线，通过请求告知服务器接口
     * @param user
     * @return
     */
    @PostMapping("/offLine")
    public Result<UserRoomDataVo> offLine(@RequestBody User user) {
        Constant.onlineUserList.remove(user.getUuid());
        String name = Constant.allUserDataList.get(user.getUuid()).getName();
        return Result.success(name + "下线了");
    }

    /**
     * 当用户选取某个好友\群聊天室的时候，获取当前用户和当前聊天室的历史消息
     * @param userRoomVo
     * @return
     */
    @PostMapping("/getUserRoomMsg")
    public Result<List<ChatMessage>> getUserRoomMsg(@RequestBody UserRoomVo userRoomVo) {

        String onlyTag = "";
        if ("1".equals(userRoomVo.getType())) {
            onlyTag = Constant.getOnlyTag(userRoomVo.getUuid(), userRoomVo.getRoomId());
        } else {
            onlyTag = userRoomVo.getRoomId();
        }
        List<ChatMessage> chatMessages = Constant.ownChatMsgList.get(onlyTag);
        return Result.success(chatMessages);
    }

    /**
     * 用户点击刷新的时候清除所有已登录的账户，更改为未登录状态，这个接口只是方便模拟前端登录而已
     * @param uuids
     * @return
     */
    @PostMapping("/cleanAllChatRoomData")
    public Result<String> cleanAllChatRoomData(String[] uuids) {
//        Constant.onlineUserList.retainAll(new ArrayList<>(uuids));
        Constant.onlineUserList.clear();
        return Result.success();
    }

    /**
     * 测试消息推送接口
     * @return
     */
    @PostMapping("/checkChat")
    public String checkChat() {
        System.out.println("接口触发checkChat");
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setSenderUuid("0000");
        chatMessage.setSendContent("接口触发checkChat => convertAndSend");
        simpMessagingTemplate.convertAndSend("/own/A004/A003/messages", chatMessage);
        chatMessage.setSendContent("接口触发checkChat => convertAndSendToUser");
        simpMessagingTemplate.convertAndSendToUser("A004", "/A003/messages", chatMessage);
        return "触发完成";
    }
}
